package bll

import (
	"context"
	"fmt"
	"gitlab.local/backend/proto/dto"
	"go-micro.dev/v4/broker"
	"google.golang.org/protobuf/proto"
	"strings"
	"sync/atomic"
	"time"
)

var (
	publisher broker.Broker
	b         = &atomic.Bool{}
)

type simulator struct {
}

func SetPublisher(p broker.Broker) {
	publisher = p
}

func publish(topic string, body []byte) error {

	return publisher.Publish(topic, &broker.Message{Body: body})
}

func (s simulator) doUpgrade0x01(ctx context.Context, id uint64, sn string, deviceType uint8, fileLength uint32) error {

	id = uint64(491052011223037314)
	sendPacket := &dto.UpgradeBSC22Data{
		UpgradeCmd: dto.BSC22UpgradeCmdType_Cmd0x01,
		DeviceType: int32(deviceType),
		Id:         id,
		Sn:         sn,
		BindLength: fileLength,
		Body:       []byte{0x01, 0x00, 0x00, 0x00},
	}
	sendPacket.Crc32 = BuildPacket(sendPacket).Crc32

	fmt.Printf("数据发送[socket] => %v\n", strings.ToLower(fmt.Sprintf("0x%X", BuildPacket(sendPacket).ToHexBytes())))

	data := &dto.UpgradeBSC22Data{
		UpgradeCmd: dto.BSC22UpgradeCmdType_Cmd0x00,
		DeviceType: int32(deviceType),
		Id:         id,
		Sn:         sn,
		BindLength: 0,
		Body:       []byte{0x81, 0x00, 0x00, 0x00},
	}

	data.Crc32 = BuildPacket(data).Crc32

	var (
		err     error
		body, _ = proto.Marshal(data)
		topic   = "signal.event.ota"
	)

	fmt.Printf("数据接收[socket] <= %v\n", strings.ToLower(fmt.Sprintf("0x%X", BuildPacket(data).ToHexBytes())))

	if err = publish(topic, body); err != nil {
		return err
	} else {
		var (
			totalRead uint32
			//startPos  uint32
			startPos  = uint32(0xa304)
			readBytes = uint32(1024)
			fSize     = fileLength / 2
		)
		go func() {
			<-time.After(time.Second * 5)
			for {
				if totalRead >= fSize {
					break
				}

				for !b.Load() {
					time.Sleep(time.Millisecond * 10)
				}

				b.Store(false)

				if err = s.createUpgradePacketOx02(id, sn, deviceType, startPos, readBytes); err != nil {
					return
				}
				startPos = startPos + readBytes
				totalRead = totalRead + readBytes
			}
			fmt.Println("读取升级包长度:", totalRead)
		}()
	}
	return nil
}

func (s simulator) dealUpgrade0x00(ctx context.Context, id uint64, sn string, deviceType uint8, bindAddress, bindLength uint32, data []byte) error {

	for b.Load() {
		time.Sleep(time.Millisecond * 10)
	}

	b.Store(true)

	return nil
}

func (s simulator) doUpgrade0x02(ctx context.Context, id uint64, sn string, deviceType uint8, bindAddress, bindLength uint32, data []byte) error {

	sendPacket := &dto.UpgradeBSC22Data{
		UpgradeCmd:  dto.BSC22UpgradeCmdType_Cmd0x02,
		DeviceType:  int32(deviceType),
		Id:          id,
		Sn:          sn,
		BindLength:  bindLength,
		BindAddress: bindAddress,
		Body:        data,
	}

	sendPacket.Crc32 = BuildPacket(sendPacket).Crc32
	fmt.Printf("数据发送[socket] => %v\n", strings.ToLower(fmt.Sprintf("0x%X", BuildPacket(sendPacket).ToHexBytes())))

	for b.Load() {
		time.Sleep(time.Millisecond * 10)
	}

	b.Store(true)
	return nil
}

func (s simulator) createUpgradePacketOx02(id uint64, sn string, deviceType uint8, startPos, fileLength uint32) error {
	data := &dto.UpgradeBSC22Data{
		UpgradeCmd:  dto.BSC22UpgradeCmdType_Cmd0x02,
		DeviceType:  int32(deviceType),
		Id:          id,
		Sn:          sn,
		BindAddress: startPos,
		BindLength:  fileLength,
		Body:        nil,
	}

	data.Crc32 = BuildPacket(data).Crc32
	body, _ := proto.Marshal(data)
	topic := "signal.event.ota"

	fmt.Printf("数据接收[socket] <= %v\n", strings.ToLower(fmt.Sprintf("0x%X", BuildPacket(data).ToHexBytes())))
	return publish(topic, body)
}
